from django.contrib.auth import authenticate, login
from django.contrib.auth import logout
from django.contrib.auth.hashers import make_password
from django.contrib.auth.models import User
from django.shortcuts import get_object_or_404
from rest_framework import status
from rest_framework.exceptions import PermissionDenied
from rest_framework.generics import ListCreateAPIView, RetrieveUpdateDestroyAPIView
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework_simplejwt.tokens import RefreshToken

from .models import User, UserRole
from .serializers import UserSerializer, UserRoleSerializer
from ..logs.service import LogService


class UserListCreateView(ListCreateAPIView):
    """
    用户列表 & 创建用户视图
    支持：GET 获取用户列表，POST 创建新用户
    """
    permission_classes = [IsAuthenticated]
    queryset = User.objects.all()
    serializer_class = UserSerializer

    def create(self, request, *args, **kwargs):
        """
        重写创建用户方法，确保密码的敏感性
        """
        # 获取请求数据
        data = request.data
        # 密码加密
        if 'password' in data:
            data['password_hash'] = make_password(data.pop('password'))  # 加密密码
        # 使用序列化器进行数据验证
        serializer = self.get_serializer(data=data)
        serializer.is_valid(raise_exception=True)
        user = serializer.save()
        return Response(UserSerializer(user).data, status=status.HTTP_201_CREATED)


class UserDetailView(RetrieveUpdateDestroyAPIView):
    """
    用户详情视图
    支持：GET 获取用户详情，PUT 修改用户信息，DELETE 删除用户
    """
    permission_classes = [IsAuthenticated]
    queryset = User.objects.all()
    serializer_class = UserSerializer
    lookup_field = 'user_id'

    def update(self, request, *args, **kwargs):
        """
        更新方法，确保部分字段的安全性
        """
        partial = kwargs.pop('partial', False)
        instance = self.get_object()
        serializer = self.get_serializer(instance, data=request.data, partial=partial)
        serializer.is_valid(raise_exception=True)

        # 如果包含密码字段，重新加密
        if 'password' in request.data:
            instance.password = make_password(request.data['password'])  # 这里直接更新密码字段
            instance.save()

        self.perform_update(serializer)
        return Response(serializer.data)

    def destroy(self, request, *args, **kwargs):
        """
        删除用户，同时处理相关联的用户角色
        """
        instance = self.get_object()
        user_roles = UserRole.objects.filter(user=instance)
        user_roles.delete()
        self.perform_destroy(instance)
        return Response(status=status.HTTP_204_NO_CONTENT)

    def reset_password(self, request, *args, **kwargs):
        """
        管理员重置用户密码接口
        """
        user = request.user
        if not user.is_staff:  # 只有管理员用户才有权限
            raise PermissionDenied("你没有权限执行此操作")

        # 获取请求中的目标用户和新密码
        username = request.data.get('username')
        new_password = request.data.get('new_password')

        if not username or not new_password:
            return Response({'detail': '用户名和新密码不能为空'}, status=status.HTTP_400_BAD_REQUEST)

        try:
            # 获取目标用户
            target_user = User.objects.get(username=username)
        except User.DoesNotExist:
            return Response({'detail': '用户不存在'}, status=status.HTTP_404_NOT_FOUND)

        # 设置新密码
        target_user.set_password(new_password)
        target_user.save()

        # 记录密码重置日志
        LogService.log_action(user, "reset_password", log_type="INFO", related_object=f"User: {target_user.username}")

        return Response({'detail': '密码重置成功'}, status=status.HTTP_200_OK)

class AssignRoleView(APIView):
    """
    分配角色视图
    支持：POST 给用户分配角色
    """
    permission_classes = [IsAuthenticated]

    def post(self, request, user_id):
        # 查找用户
        user = get_object_or_404(User, user_id=user_id)
        # 验证和分配角色
        serializer = UserRoleSerializer(data=request.data)
        if serializer.is_valid():
            # 将角色与用户关联
            serializer.save(user=user)
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)


class CustomLoginAPIView(APIView):
    """
    自定义登录接口，前后端分离模式下登录
    """

    def post(self, request, *args, **kwargs):
        username = request.data.get('username')
        password = request.data.get('password')

        if not username or not password:
            return Response({'detail': '用户名和密码不能为空'}, status=status.HTTP_400_BAD_REQUEST)

        user = authenticate(request, username=username, password=password)
        if user is not None:
            # 登录用户
            login(request, user)
            # 记录登录日志
            LogService.log_login(user)

            # 生成 JWT 令牌
            refresh = RefreshToken.for_user(user)
            return Response({
                'refresh': str(refresh),
                'access': str(refresh.access_token),
                'detail': '登录成功'
            }, status=status.HTTP_200_OK)
        else:
            return Response({'detail': '无效的用户名或密码'}, status=status.HTTP_400_BAD_REQUEST)


class CustomLogoutAPIView(APIView):
    """
    自定义登出接口，前后端分离模式下登出
    """
    def post(self, request, *args, **kwargs):
        user = request.user  # 获取当前已登录的用户

        if not user.is_authenticated:
            return Response({'detail': '用户未登录'}, status=status.HTTP_400_BAD_REQUEST)

        # 记录登出日志
        LogService.log_action(user, "logout", log_type="INFO", related_object="Logout")

        # 执行登出操作，清除 Session
        logout(request)

        return Response({'detail': '登出成功'}, status=status.HTTP_200_OK)


class ResetOwnPasswordAPIView(APIView):
    """
    管理员重置自己密码接口
    """
    permission_classes = [IsAuthenticated]  # 需要认证

    def post(self, request, *args, **kwargs):
        # 确保当前用户是管理员
        user = request.user
        if not user.is_staff:  # 只有管理员用户才有权限
            raise PermissionDenied("你没有权限执行此操作")

        # 获取新密码
        new_password = request.data.get('new_password')

        if not new_password:
            return Response({'detail': '新密码不能为空'}, status=status.HTTP_400_BAD_REQUEST)

        # 重置密码
        user.set_password(new_password)
        user.save()

        # 记录密码重置日志
        LogService.log_action(user, "reset_own_password", log_type="INFO", related_object=f"User: {user.username}")

        return Response({'detail': '密码重置成功'}, status=status.HTTP_200_OK)

